<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        #img {
            display: none;
        }

        #myCanvas {
            margin-left: 100px;
            margin-top: 100px;
        }

        .canvas-wrap {
            position: relative;
        }

        .canvas-wrap #myImgCanvas {
            position: absolute;
            top: 0;
            left: 0;
        }

        .canvas-wrap #middleLayerCanvas {
            position: absolute;
            top: 0;
            left: 0;
        }

        .canvas-wrap #myLayerCanvas {
            position: absolute;
            top: 0;
            left: 0;
            z-index: 100;
        }

        #button {
            position: absolute;
            right: 0;
        }

        #button2 {
            position: absolute;
            right: 0;
            top: 50px;
        }
    </style>
</head>

<body> 
    <!-- 注意这里的图片一定要用网络图片还有属性crossorigin="anonymous",不然将canvas对象转换为图片时会报错! -->
    <img id="img" crossorigin="anonymous" src="https://cube.elemecdn.com/6/94/4d3ea53c084bad6931a56d5158a48jpeg.jpeg" alt="">

    <div class="canvas-wrap">
        <!-- canvas背景图片层-图片展示 -->
        <canvas id="myImgCanvas" width="500px" height="500px"></canvas>
        <!-- canvas生成标注层-记录标注 -->
        <canvas id="middleLayerCanvas" width="500px" height="500px"></canvas>
        <!-- canvas绘画标注层-用于绘画标注 -->
        <canvas id="myLayerCanvas" width="500px" height="500px"></canvas>
    </div>
    <button id="button">重新绘制</button>
    <button id="button2">合并canvas并下载</button>
    <script>
        // 图片展示canvas
        var myImgCanvas = document.getElementById('myImgCanvas')
        // 记录标记canvas
        var middleLayerCanvas = document.getElementById('middleLayerCanvas')
        // 绘画标记canvas
        var myLayerCanvas = document.getElementById('myLayerCanvas')
        // 获取图片对象
        var img = document.getElementById('img')
        // 初始化图片canvas,并绘制图片
        var imgCTX = myImgCanvas.getContext("2d");
        img.onload = () => {
            imgCTX.drawImage(img, 0, 0, 500, 500)
        }
        //初始化中间canvas
        var middleLayerCTX = middleLayerCanvas.getContext('2d')
        middleLayerCTX.strokeStyle = 'red';
        middleLayerCTX.lineWidth = '6'
        //初始化顶部图层canvas
        var layerCTX = myLayerCanvas.getContext("2d");
        layerCTX.strokeStyle = 'red';
        layerCTX.lineWidth = '6'

        // 声明遍历记录绘制标记时开始的坐标和松开鼠标的坐标
        var startX;
        var startY;
        var endX;
        var endY;
        // 给绘画canvas绑定鼠标按下事件；1.记录鼠标按下时的坐标；2.给绘画canvas绑定鼠标移动事件
        myLayerCanvas.onmousedown = (e) => {
            console.log('记录鼠标按下的坐标', e.layerX, e.layerY)
            startX = e.layerX
            startY = e.layerY
            myLayerCanvas.addEventListener('mousemove', drawRect)
        }
        // 鼠标松开时清空绘画层canvas，并将绘画的标记记录到标记层
        myLayerCanvas.onmouseup = e => {
            layerCTX.clearRect(0, 0, 500, 500)
            myLayerCanvas.removeEventListener('mousemove', drawRect)
            console.log('松开鼠标', e)
            console.log('鼠标松开时的坐标', e.layerX, e.layerY)
            endX = e.layerX
            endY = e.layerY
            // layerCTX.strokeRect(startX, startY, endX - startX, endY - startY)
            middleLayerCTX.strokeRect(startX, startY, endX - startX, endY - startY)
        }
        // 鼠标移动事件处理函数-实现实时绘画矩形
        function drawRect(e) {
            console.log('鼠标按下后绑定移动事件', e)
            layerCTX.clearRect(0, 0, 500, 500)
            layerCTX.strokeRect(startX, startY, e.layerX - startX, e.layerY - startY)
        }
        document.getElementById('button').addEventListener('click', reset)
        // 情况标记层重新绘制标注
        function reset() {
            console.log('123')
            middleLayerCTX.clearRect(0, 0, 500, 500)
        }

        document.getElementById('button2').addEventListener('click', mergeCanvas)
        // 将图片层canvas和标注层canvas合并并导出图片
        function mergeCanvas() {
            imgCTX.drawImage(middleLayerCanvas, 0, 0, 500, 500)
            /*
            **注意讲canvas对象导出为图片的坑:
            **1.如果图片层canvas绘制的图片是本地图片,那么将canvas对象转换为图片时会一直报错,网上的解决方法是给图片添加跨域属性crossorigin="anonymous";这个解决方法对于本地图片是没有用的,不管怎么都会报哪个错;所以图片层canvas的图片一定要用图片链接,而不是本地图片. 使用图片链接并给图片对象添加crossorigin="anonymous"属性
            */
            
            var image = myImgCanvas.toDataURL("image/png");
            const link = document.createElement('a')
            link.style.display = 'none'
            link.href = image
            link.download = '合并canvas.png'
            document.body.appendChild(link)
            link.click()
            document.body.removeChild(link)
        }

    </script>
</body>

</html>